﻿using System;

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using Microsoft.WindowsMobile.Status;
using System.IO;
using System.Globalization;
using Senthil.Mobile.WhereAmI;
using System.Reflection;
using System.Text.RegularExpressions;

namespace LocationLogger
{
    public partial class MainForm : Form
    {
        ILocationChangeNotifier locationChangeNotifer;
        Route route = new Route();

        DateTime? lastLocationChangeDateTime = null;
        TimeSpan timeSinceStart;
        State state = State.Recording;

        int locationsCount = 1;

        public MainForm()
        {
            InitializeComponent(); 
            
            if (!LocationChangeNotifier.IsDeviceLocationChangeNotificationEnabled())
            {
                DialogResult result = MessageBox.Show(
                    "Cell broadcast doesn't seem to be enabled in your phone. Do you still want to continue?",
                    Program.ApplicationName,
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question,
                    MessageBoxDefaultButton.Button1);

                if (result != DialogResult.Yes)
                {
                    Application.Exit();
                    return;
                }
            }

            SetStatusText();

            route.OperatorName = SystemState.PhoneOperatorName;

            locationChangeNotifer = new LocationChangeNotifier();
            locationChangeNotifer.LocationChanged += new EventHandler<LocationChangeNotificationEventArgs>(locationChangeNotifer_LocationChanged);
            locationChangeNotifer.Initialize();
        }

        private void SetStatusText()
        {
            // statusLabel.Text = "Currently: " + state.ToString();
        }

        void locationChangeNotifer_LocationChanged(object sender, LocationChangeNotificationEventArgs e)
        {
            if (state == State.Paused)
                return;

            HandlePhoneLocationChange(e.NewLocation, e.CellTowerId);
        }

        private void HandlePhoneLocationChange(string locationName, string cellTowerId)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new Action(() => HandlePhoneLocationChange(locationName, cellTowerId)));
                return;
            }

            locationName = locationName.Trim();

            Location location = null;
            List<Location> locations;

            bool locationAlreadyExists = false;

            if (route.TryGetLocation(locationName, cellTowerId, out locations))
            {
                // We got a cell tower id match, so simply reuse the location
                // otherwise, we're not sure, so construct a new location object with a unique name
                if (locations.Count > 0 && locations[0].CellTowerId == cellTowerId)
                {
                    location = locations[0];
                    locationAlreadyExists = true;
                }
                else
                {
                    location = CreateNextIncrementedLocation(locationName, cellTowerId);
                }
            }
            else
            {
                // There was no match. If locationName is empty (cell broadcast off)
                // generate incremented location name
                if (string.IsNullOrEmpty(locationName))
                {
                    location = CreateNextIncrementedLocation(locationName, cellTowerId);
                }
                else
                {
                    location = new Location(locationName, cellTowerId);
                }
            }

            TimeSpan timeSpan = TimeSpan.Zero;
            if (lastLocationChangeDateTime != null)
            {
                timeSpan = DateTime.Now.Subtract(lastLocationChangeDateTime.Value);
            }

            lastLocationChangeDateTime = DateTime.Now;

            if (!locationAlreadyExists)
            {
                LocationGroup group = new LocationGroup(location.Name);
                group.AddLocation(location);

                route.AddLocationGroup(group);
            }

            route.AddNextRoutePoint(location, timeSpan);

            timeSinceStart = timeSinceStart.Add(timeSpan);
            logListView.Items.Insert(0,
                new ListViewItem(new string[] { location.Name, cellTowerId, timeSinceStart.ToString() }));
        }

        private Location CreateNextIncrementedLocation(string locationName, string cellTowerId)
        {
            string newLocationName = (locationName ?? "") + GetNextAutoIncrementedLocationName();
            return new Location(newLocationName, cellTowerId);
        }

        private string GetNextAutoIncrementedLocationName()
        {
            return (locationsCount++).ToString();
        }

        private void menuItem1_Click(object sender, EventArgs e)
        {
            locationChangeNotifer.Dispose();
            route.Name = string.Format("{0} {1}", route.StartGroup.Name, route.DestinationGroup.Name);
            RouteManager.SaveNew(route);
            
            Application.Exit();
        }

        private void clearScreenMenuItem_Click(object sender, EventArgs e)
        {
            logListView.Items.Clear();
        }

        private void aboutMenuItem_Click(object sender, EventArgs e)
        {
            using (About about = new About())
            {
                about.ApplicationName = Program.ApplicationName;
                about.Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
                about.ApplicationDescription = "Records location changes based on cell broadcast and cell tower id.";
                about.Author = "Senthil Kumar Selvaraj";
                about.ContactInfo = "senthil.thecoder@gmail.com";

                about.ShowDialog();
            }
        }

        enum State
        {
            Recording,
            Paused
        }

        private void actionLabel_Click(object sender, EventArgs e)
        {
            if (state == State.Recording)
                ChangeStateTo(State.Paused);
            else
                ChangeStateTo(State.Recording);
        }

        private void ChangeStateTo(State newState)
        {
            switch (newState)
            {
                case State.Recording: 
                    lastLocationChangeDateTime = DateTime.Now; 
                    break;
            }

            state = newState;

            actionLabel.Text = state == State.Recording ? "Pause" : "Resume";
            SetStatusText();
        }

        private void MainForm_Resize(object sender, EventArgs e)
        {
            ResizeLogListViewColumns();
        }

        private void ResizeLogListViewColumns()
        {
            int screenWidth = this.ClientRectangle.Width;

            int widthForTimeSpan = logListView.Columns[2].Width;
            int remainingScreenWidth = screenWidth - widthForTimeSpan;
            int widthPerColumn = remainingScreenWidth / 2;

            logListView.Columns[0].Width = logListView.Columns[1].Width = widthPerColumn;
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            ResizeLogListViewColumns();
        }
    }
}